package com.x52im.rainbowchat.http.logic.pay.redenvelope;

import com.eva.framework.dbpool.DBShell;
import org.apache.commons.lang.math.RandomUtils;

import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

public class GenSubEnvelope {
    /**
     * 收到单个红包最大值
     */
    private static final int MAX_AMOUNT = 200000;

    public static void main(String[] args) throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String batch = simpleDateFormat.format(new Date());

        StringBuffer sql = new StringBuffer();
        sql.append("insert into redenv_analyse(batch, id, #x) values('").append(batch).append("',?,#y)");

        int count = 8; //红包个数
        StringBuffer numx = new StringBuffer();
        StringBuffer valuex = new StringBuffer();
        for (int i = 1; i <= count; i++) {
            numx.append("num").append(i).append(",");
            valuex.append("?,");
        }
        numx.setLength(numx.length() - 1);
        valuex.setLength(valuex.length() - 1);

        String xxx = sql.toString().replaceAll("#x", numx.toString()).replaceAll("#y", valuex.toString());

        DBShell dbShell = new DBShell();
        for (int i = 1; i <= 100; i++) {
            int total = 1000; //发红包的总金额
            int type = 0;//发送类型
            int[] redPacket = generateArr(total, count, type);
            redPacket = randomArray(redPacket);

            Object[] objs = new Object[count + 1];
            objs[0] = i;
            for (int j = 0; j < redPacket.length; j++) {
                objs[j + 1] = redPacket[j];
            }

            dbShell.update(xxx, objs, true);
            System.out.println(Arrays.toString(redPacket));

//            ArrayList<String> yuan = new ArrayList<>();
//            for (int x : redPacket) {
//                yuan.add(fenToYuan(String.valueOf(x)));
//            }
//            System.out.println(Arrays.toString(yuan.toArray()));
        }

        /*
        int total = 1000; //发红包的总金额
        int count = 7; //红包个数
        int type = 0;//发送类型
//        System.out.println(String.format("红包发送总金额为：%s分，发送个数为:%s", total, count));
        int[] redPacket = generateArr(total, count, type);
        System.out.println(Arrays.toString(redPacket));
//        double total2 = 0;
//        ArrayList<String> yuan = new ArrayList<>();
//        for (int i : redPacket) {
//            total2 += i;
//            yuan.add(fenToYuan(String.valueOf(i)));
//        }
//        System.out.println("发送红包总金额:" + total2 + "分，合计" + (fenToYuan(String.valueOf(total2))) + "元");
//        System.out.println("红包详情:" + yuan.toString());
*/
    }


    /**
     * 分转元
     *
     * @param amount
     * @return
     */
    public static String fenToYuan(String amount) {
        NumberFormat format = NumberFormat.getInstance();
        try {
            Number number = format.parse(amount);
            double temp = number.doubleValue() / 100.0;
            format.setGroupingUsed(false);
            format.setMaximumFractionDigits(2);
            amount = format.format(temp);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return amount;
    }

    /**
     * 元转分
     *
     * @param amount
     * @return
     */
    public static String yuanTofen(String amount) {
        NumberFormat format = NumberFormat.getInstance();
        try {
            Number number = format.parse(amount);
            double temp = number.doubleValue() * 100.0;
            format.setGroupingUsed(false);
            format.setMaximumFractionDigits(2);
            amount = format.format(temp);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return amount;
    }


    /**
     * 随机打乱数组
     */
    public static void sort(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            int p = RandomUtils.nextInt(i + 1);
            int tmp = arr[i];
            arr[i] = arr[p];
            arr[p] = tmp;
        }
    }

    /**
     * 生成红包数组
     *
     * @param amount 红包总金额（单位分）
     * @param count  发包个数
     * @param type   发包类型（0、随机红包，1、定额红包）
     * @return 红包数组
     */

    public static int[] generateArr(Integer amount, Integer count, Integer type) throws Exception {
        // 定义返回的数组
        int[] array = new int[count];

        if (count == 1) {
            return new int[]{amount};
        }

        switch (type) {
            case 0:
                // 默认分配1至每一位
                for (int i = 0; i < array.length; i++) {
                    array[i] = 1;
                }
                int surplus_currency = amount - array.length;// 剩余金额数
                int surplus_number = array.length;// 剩余需追加的数量

                for (int i = 0; i < array.length; i++) {
                    // 没值可以追加了
                    if (surplus_currency == 0) {
                        break;
                    }

                    // (总数-（总包-i）*最小值) / (总包 - i) 随机安全值算法
                    int safe_total = (int) Math.floor((amount - (count - i)) / (count - i));
                    if (safe_total == 0) {// 随机值不能为0
                        safe_total = 1;
                    }

                    // 该次随机值
                    int randomint = surplus_currency >= safe_total - 1 ? safe_total : surplus_currency + 1;
                    // 下次可能最大能剩余值
                    int nextMax_currency = (MAX_AMOUNT - 1) * (surplus_number - 1);
                    // 最小的随机数     剩余金额-剩余最大随机的总数（不含这一次）
                    int minRandom = surplus_currency - nextMax_currency;
                    if (minRandom < 0) {
                        minRandom = 0;
                    }

                    // 规避一些特殊情况,每个接近2000或1时会发生
                    boolean must = (surplus_currency - count * MAX_AMOUNT <= 2 && surplus_currency - count * MAX_AMOUNT >= 0)
                            /*|| surplus_currency < packet_number * 2*/;
                    // 控制安全随机值           随机安全值不能大于最大限制，并且不能小于最小限 制
                    if (safe_total < minRandom || safe_total > MAX_AMOUNT || must) {
                        safe_total = MAX_AMOUNT;
                        // 该次随机值
                        randomint = surplus_currency >= safe_total - 1 ? safe_total : surplus_currency + 1;
                        // 下次可能最大能剩余值
                        nextMax_currency = (randomint - 1) * (surplus_number - 1);
                        // 最小的随机数     剩余金额-剩余最大随机的总数（不含这一次）
                        minRandom = surplus_currency - nextMax_currency;
                        if (minRandom < 0) {
                            minRandom = 0;
                        }
                    }

                    // 下一次最大的随机值
                    int nextMaxRandomInt = nextMax_currency - (surplus_currency - (randomint - 1));
                    Integer maxRandom = nextMaxRandomInt <= 0 ? nextMaxRandomInt + randomint : null;
                    // 能随机          剩余的金额  - 最大随机数 >  最大随机数  * 剩余数量
                    boolean canRandom = surplus_currency - (randomint - 1) > nextMax_currency ||
                            nextMaxRandomInt > (randomint - 1) || minRandom != 0;

                    int addNumber; // 追加的金额
                    if (canRandom && (minRandom + 1) != randomint && !(minRandom == randomint && minRandom == safe_total)) {
                        addNumber = myRandom(minRandom, maxRandom == null ? randomint : maxRandom - 1);
                    } else {
                        addNumber = randomint - 1;
                    }
                    array[i] += addNumber;
                    surplus_currency -= addNumber;
                    surplus_number--;
                }
                break;
            case 1:
                // 定额红包校验
                array = new int[count];
                for (int i = 0; i < array.length; i++) {
                    array[i] = amount / count;
                }
                break;
            default:
                throw new Exception("类型错误！");
        }

        return array;
    }

    // 再次混淆
    public static int[] randomArray(int[] sourceArray) {
        List<Integer> list = Arrays.stream(sourceArray).boxed().collect(Collectors.toList());
        List<Integer> randomList = new CopyOnWriteArrayList<>();
        do {
            int randomIndex = Math.abs(new Random().nextInt(list.size()));
            randomList.add(list.remove(randomIndex));
        } while (list.size() > 0);
        int[] returnArray = new int[randomList.size()];
        for (int i = 0; i < randomList.size(); i++) {
            returnArray[i] = randomList.get(i);
        }
        return returnArray;
    }

    public static int myRandom(int min, int randomint) {
        if (min == 0) {
            return RandomUtils.nextInt(randomint);
        } else {
            int nextInt = RandomUtils.nextInt(randomint - min);
            return nextInt + min;
        }
    }

}
